package com.winhxd.b2c.customer.api;

import com.winhxd.b2c.common.cache.Cache;
import com.winhxd.b2c.common.cache.RedisLock;
import com.winhxd.b2c.customer.config.PayWithdrawalConfig;
import com.winhxd.b2c.common.constant.BusinessCode;
import com.winhxd.b2c.common.constant.CacheName;
import com.winhxd.b2c.common.context.CustomerUser;
import com.winhxd.b2c.common.context.UserContext;
import com.winhxd.b2c.common.domain.ResponseResult;
import com.winhxd.b2c.common.domain.common.ApiCondition;
import com.winhxd.b2c.common.domain.common.PagedCondition;
import com.winhxd.b2c.common.domain.customer.condition.CustomerApplyWithDrawCondition;
import com.winhxd.b2c.common.domain.customer.condition.ShoppingMallRuleCondition;
import com.winhxd.b2c.common.domain.customer.vo.CustomerMyIntegralVO;
import com.winhxd.b2c.common.domain.customer.vo.CustomerWithdrawalsInfoVO;
import com.winhxd.b2c.common.domain.customer.vo.ShoppingMallRuleVO;
import com.winhxd.b2c.common.exception.BusinessException;
import com.winhxd.b2c.common.util.IpUtil;
import com.winhxd.b2c.common.util.JsonUtil;
import com.winhxd.b2c.customer.service.CustomerIntegralDetailService;
import com.winhxd.b2c.customer.service.CustomerRevenueService;
import com.winhxd.b2c.customer.service.ShoppingMallRuleService;
import com.winhxd.b2c.customer.util.NumberUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 用户收益积分
 *
 * @author lt
 * @date 2019-01-12 11:01:11
 */
@Api(tags = "customer-revenue")
@RestController
@RequestMapping(value = "/api-customer/", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class ApiCustomerRevenueController {
    private static final Logger logger = LoggerFactory.getLogger(ApiCustomerRevenueController.class);

    @Autowired
    private CustomerRevenueService customerRevenueService;

    @Autowired
    private CustomerIntegralDetailService customerIntegralDetailService;

    @Autowired
    private PayWithdrawalConfig payWithdrawalConfig;

    @Autowired
    private ShoppingMallRuleService shoppingMallRuleService;

    @Autowired
    private Cache cache;

    /**
     * @param condition
     * @return
     */
    @ApiOperation(value = "查询我的积分列表")
    @ApiResponses({ @ApiResponse(code = BusinessCode.CODE_OK, message = "成功"),
            @ApiResponse(code = BusinessCode.CODE_1001, message = "服务器内部异常"),
            @ApiResponse(code = BusinessCode.CODE_1002, message = "登录凭证无效")})
    @RequestMapping(value = "revenue/2070/v1/getMyIntegralList", method = RequestMethod.POST)
    public ResponseResult<CustomerMyIntegralVO> getMyIntegralList(@RequestBody PagedCondition condition) {
        ResponseResult<CustomerMyIntegralVO> responseResult = new ResponseResult<>();
        logger.info("查询我的积分列表, 入数：customerId={}", condition.getCustomerId());
        CustomerUser customerUser = UserContext.getCurrentCustomerUser();
        CustomerMyIntegralVO vo = new CustomerMyIntegralVO();
        vo.setRemainIntegral(customerRevenueService.getCustomerRevenue(condition.getCustomerId(), customerUser.getLevel()).getRemainIntegral());
        vo.setIntegralList(customerIntegralDetailService.getMyIntegralList(condition.getCustomerId(), condition.getPageNo(), condition.getPageSize()));
        responseResult.setData(vo);
        logger.info("查询我的积分列表, 返数：{}", JsonUtil.toJSONString(vo));
        return responseResult;
    }

    @ApiOperation(value = "查询用户提现申请页")
    @ApiResponses({ @ApiResponse(code = BusinessCode.CODE_OK, message = "成功"),
            @ApiResponse(code = BusinessCode.CODE_1001, message = "服务器内部异常")})
    @RequestMapping(value = "revenue/2071/v1/getCustomerWithdrawalsInfo", method = RequestMethod.POST)
    public ResponseResult<CustomerWithdrawalsInfoVO> getCustomerWithdrawalsInfo(@RequestBody ApiCondition apiCondition) {
        ResponseResult<CustomerWithdrawalsInfoVO> result = new ResponseResult<>();
        try {
            CustomerUser customerUser = UserContext.getCurrentCustomerUser();
            logger.info("查询用户提现申请页详情,customerId={}", customerUser.getCustomerId());
            CustomerWithdrawalsInfoVO customerWithdrawalsInfoVO = customerRevenueService.getCustomerWithdrawalsInfo(customerUser.getCustomerId(), customerUser.getLevel());
            result.setData(customerWithdrawalsInfoVO);
            logger.info("查询用户提现申请页详情, 返参：{}", JsonUtil.toJSONString(customerWithdrawalsInfoVO));
        }catch (Exception e){
            result.setCode(BusinessCode.CODE_1001);
            result.setMessage("服务器内部错误");
            logger.error("查询用户提现申请页详情,异常{}",e);
        }
        return result;
    }

    @ApiOperation(value = "用户提现")
    @ApiResponses({ @ApiResponse(code = BusinessCode.CODE_OK, message = "成功"),
            @ApiResponse(code = BusinessCode.CODE_1001, message = "服务器内部异常"),
            @ApiResponse(code = BusinessCode.CODE_610035, message = "提取限额不得大于实际账户余额"),
            @ApiResponse(code = BusinessCode.CODE_610032, message = "提现金额输入有误"),
            @ApiResponse(code = BusinessCode.CODE_610015, message = "手机号为空"),
            @ApiResponse(code = BusinessCode.CODE_610038, message = "当前门店没有可提现金额"),
            @ApiResponse(code = BusinessCode.CODE_611107, message = "提现金额不得小于最小提现金额"),
            @ApiResponse(code = BusinessCode.CODE_611108, message = "单笔提现不得大于单日最大提现金额"),
            @ApiResponse(code = BusinessCode.CODE_611105, message = "提现操作过于频繁"),
            @ApiResponse(code = BusinessCode.CODE_611114, message = "提现金额不得大于当日剩余提现额度"),
            @ApiResponse(code = BusinessCode.CODE_610026, message = "门店和微信钱包不匹配"),
            @ApiResponse(code = BusinessCode.CODE_611113, message = "账户已被冻结"),
            @ApiResponse(code = BusinessCode.CODE_611112, message = "查询门店用户信息不存在")
    })
    @RequestMapping(value = "revenue/2072/v1/customerWithdrawals", method = RequestMethod.POST)
    public ResponseResult<Void> customerWithdrawals(@RequestBody CustomerApplyWithDrawCondition condition) {
        ResponseResult<Void> result = new ResponseResult<>();
        CustomerUser customerUser = UserContext.getCurrentCustomerUser();
        String lockKey = CacheName.CUSTOMER_WITHDRAWALS_CACHELOCK + customerUser.getCustomerId();
        RedisLock redisLock = new RedisLock(cache, lockKey, 5);
        if (!redisLock.tryLock(3, TimeUnit.SECONDS)) {
            logger.warn("用户提现,customerId=" + customerUser.getCustomerId() + ",提现操作过于频繁");
            throw new BusinessException(BusinessCode.CODE_611105, "提现操作过于频繁");
        }
        try {
            logger.info("用户提现,customerId=" + customerUser.getCustomerId() + ",condition=" + JsonUtil.toJSONString(condition));
            String ip= IpUtil.getIpAddr();
            condition.setSpbillCreateIp(ip);
            valiApplyWithDrawCondition(customerUser.getCustomerId(), condition);
            customerRevenueService.customerWithdrawals(customerUser, condition);
            logger.info("用户提现,customerId=" + customerUser.getCustomerId() + ",完成");
        }catch (BusinessException be){
            result.setCode(be.getErrorCode());
            result.setMessage(be.getMessage());
            logger.warn("用户提现,customerId=" + customerUser.getCustomerId() + ",错误:", be.getMessage());
        }catch (Exception e){
            result.setCode(BusinessCode.CODE_1001);
            result.setMessage("服务器内部错误");
            logger.error("用户提现,customerId=" + customerUser.getCustomerId() +",异常:", e);
        }finally {
            redisLock.unlock();
        }
        return result;
    }

    private void valiApplyWithDrawCondition(Long customerId, CustomerApplyWithDrawCondition condition) {
        BigDecimal totalFee = condition.getTotalFee();
        if (totalFee == null || (!NumberUtil.isPositiveDecimal(totalFee.toString()) && !NumberUtil.isPositiveInteger(totalFee.toString()))) {
            throw new BusinessException(BusinessCode.CODE_610032, "提现金额输入有误");
        }
        String totalFeeStr = totalFee.toString();
        if (totalFeeStr.indexOf(".") != -1) {
            //最多支持两位小数
            String[] totalFeeArr = totalFeeStr.split("\\.");
            if (totalFeeArr != null && totalFeeArr[1].length() > 2) {
                throw new BusinessException(BusinessCode.CODE_610032, "提现金额超过了两位小数");
            }
        }
        // 获取商户配置
        ShoppingMallRuleCondition shoppingMallRuleCondition = new ShoppingMallRuleCondition();
        shoppingMallRuleCondition.setSysUserId(customerId);
        ShoppingMallRuleVO shoppingMallRule = shoppingMallRuleService.findShoppingMallRule(shoppingMallRuleCondition);
        if (Objects.nonNull(shoppingMallRule)){
            if (totalFee.compareTo(shoppingMallRule.getReflectRule()) < 0) {
                throw new BusinessException(BusinessCode.CODE_611107, "提现金额不得小于最小提现金额");
            }
        }
        // 最大提现额度
        BigDecimal max = payWithdrawalConfig.getMaxMoney();
        if (totalFee.compareTo(max) > 0) {
            throw new BusinessException(BusinessCode.CODE_611108, "单笔提现不得大于" + max + "元");
        }

        BigDecimal todayTotalFee = customerRevenueService.getSumTodayTotalFeeByCustomerId(customerId);
        if (todayTotalFee.compareTo(totalFee)  == -1){
            throw new BusinessException(BusinessCode.CODE_611114, "提现金额不得大于当日剩余提现额度");
        }

    }
}
